package com.robertux.leaderboard.util.gestoresModelos;

import java.math.BigDecimal;
import java.util.List;

import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;

import org.apache.log4j.Logger;

import com.robertux.leaderboard.beans.entities.PuntosAcumulado;

public class GestorPuntosAcumulados {
	private GestorEntidades<PuntosAcumulado> gestorPuntos;
	private Logger logger;
	
	public GestorPuntosAcumulados() {
		this.gestorPuntos = new GestorEntidades<PuntosAcumulado>();
		this.logger = Logger.getLogger(this.getClass());
	}
	
	public GestorPuntosAcumulados(GestorEntidades<PuntosAcumulado> gestor) {
		this.gestorPuntos = gestor;
		this.logger = Logger.getLogger(this.getClass());
	}
	
	public List<PuntosAcumulado> getPuntos(int usuarioId) {
		TypedQuery<PuntosAcumulado> qry = this.gestorPuntos.getEntityManager().createQuery("SELECT puntos FROM PuntosAcumulado puntos WHERE puntos.usuario.id = :usuarioId ORDER BY puntos.id", PuntosAcumulado.class);
		qry.setParameter("usuarioId", usuarioId);
		
		try {
			return qry.getResultList();
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar los puntos acumulados del usuario con Id " + usuarioId + ": " + e.getMessage(), e);
			return null;
		}
	}
	
	public List<PuntosAcumulado> getPuntos(int usuarioId, int anio, int mes) {
		TypedQuery<PuntosAcumulado> qry = this.gestorPuntos.getEntityManager().createQuery("SELECT puntos FROM PuntosAcumulado puntos WHERE puntos.usuario.id = :usuarioId AND FUNC('YEAR', puntos.fecha) = :anio AND FUNC('MONTH', puntos.fecha) = :mes ORDER BY puntos.id", PuntosAcumulado.class);
		qry.setParameter("usuarioId", usuarioId);
		qry.setParameter("anio", anio);
		qry.setParameter("mes", mes);
		
		try {
			return qry.getResultList();
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar los puntos acumulados del usuario con Id " + usuarioId + ": " + e.getMessage(), e);
			return null;
		}
	}
	
	public PuntosAcumulado getPuntos(int usuarioId, int gprdId, int anio, int mes) {
		TypedQuery<PuntosAcumulado> qry = this.gestorPuntos.getEntityManager().createQuery("SELECT puntos FROM PuntosAcumulado puntos WHERE puntos.usuario.id = :usuarioId AND FUNC('YEAR', puntos.fecha) = :anio AND FUNC('MONTH', puntos.fecha) = :mes AND puntos.grupoProducto.id = :gprdId", PuntosAcumulado.class);
		qry.setParameter("usuarioId", usuarioId);
		qry.setParameter("anio", anio);
		qry.setParameter("mes", mes);
		qry.setParameter("gprdId", gprdId);
		
		try {
			return qry.getSingleResult();
		} catch (NoResultException nrE) {
			return null;
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar los puntos acumulados del usuario con Id " + usuarioId + ": " + e.getMessage(), e);
			return null;
		}
	}
	
	public BigDecimal getTotalPuntos(int usuarioId) {
		TypedQuery<BigDecimal> qry = this.gestorPuntos.getEntityManager().createQuery("SELECT SUM(COALESCE(puntos.puntos, 0)) FROM PuntosAcumulado puntos WHERE puntos.usuario.id = :usuarioId", BigDecimal.class);
		qry.setParameter("usuarioId", usuarioId);
		
		try {
			return qry.getSingleResult();
		} catch (NoResultException nrE) {
			return BigDecimal.ZERO;
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar el total de los puntos acumulados del usuario con Id " + usuarioId + ": " + e.getMessage(), e);
			return BigDecimal.ZERO;
		}
	}
	
	public BigDecimal getTotalPuntos(int usuarioId, int anio, int mes) {
		TypedQuery<BigDecimal> qry = this.gestorPuntos.getEntityManager().createQuery("SELECT COALESCE(SUM(puntos.puntos), 0) FROM PuntosAcumulado puntos WHERE puntos.usuario.id = :usuarioId AND FUNC('YEAR', puntos.fecha) = :anio AND FUNC('MONTH', puntos.fecha) = :mes", BigDecimal.class);
		qry.setParameter("usuarioId", usuarioId);
		qry.setParameter("anio", anio);
		qry.setParameter("mes", mes);
		
		try {
			return qry.getSingleResult();
		} catch (NoResultException nre) {
			return BigDecimal.ZERO;
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar el total de los puntos acumulados del usuario con Id " + usuarioId + ": " + e.getMessage(), e);
			return BigDecimal.ZERO;
		}
	}
	
	public boolean agregarPuntos(PuntosAcumulado puntos) {
		try {
			this.gestorPuntos.persistir(puntos);
			return true;
		} catch (Exception e) {
			this.logger.error("Error tratando de persistir los puntos acumulados: " + e.getMessage(), e);
			return false;
		}
	}
	
	public boolean actualizarPuntos(PuntosAcumulado puntos) {
		try {
			this.gestorPuntos.actualizar(puntos);
			return true;
		} catch (Exception e) {
			this.logger.error("Error tratando de actualizar los de puntos acumulados: " + e.getMessage(), e);
			return false;
		}
	}
	
	public boolean delPuntos(PuntosAcumulado puntos) {
		try {
			this.gestorPuntos.eliminar(puntos);
			return true;
		} catch (Exception e) {
			this.logger.error("Error tratando de eliminar los de puntos acumulados: " + e.getMessage(), e);
			return false;
		}
	}
}
